# +----------------------------------------------------------------------
# | ChatWork
# +----------------------------------------------------------------------
# | 这不是一个自由软件,您只能在不用于商业目的的前提下对程序代码进行修改和使用。
# | 任何企业和个人不允许对程序代码以任何形式任何目的再发布,商业使用请获取授权。
# +----------------------------------------------------------------------
# | Author: ChatWork Team <2474369941@qq.com>
# +----------------------------------------------------------------------
import json
import time
from tortoise.queryset import Q
from common.utils.urls import UrlUtil
from hypertext import PagingResult
from exception import AppException
from common.enums.agent import AgentEnum
from common.models.agents import AgentRobotModel
from common.models.agents import AgentRobotInstructModel
from apps.api.schemas.agent.robot import instruct_schema as schema
from apps.api.service.agent.robot.teamed_service import RobotTeamedService


class RobotInstructService:
    """ 智能体指令服务类 """

    @classmethod
    async def lists(cls, params: schema.RobotInstructSearchIn, user_id: int) \
            -> PagingResult[schema.RobotInstructListVo]:
        """
        指令列表。

        Args:
            params (schema.RobotInstructSearchIn): 指令查询参数。
            user_id (int): 用户ID。

        Returns:
            PagingResult[schema.RobotInstructListVo]: 指令分页列表Vo。

        Author:
            zero
        """
        # 验证智能体
        robot = await AgentRobotModel.filter(code=params.bot, is_delete=0).first()
        if robot is None:
            raise AppException("智能体不存在!")
        if robot.is_disable:
            raise AppException("智能体被禁用!")

        # 验证权限
        if robot.user_id != user_id:
            await RobotTeamedService.has_permission(robot.code, user_id, AgentEnum.POWER_VIEW)

        # 查询数据
        _where = [Q(robot_id=robot.id)]
        _model = AgentRobotInstructModel.filter(*_where).order_by("-sort", "-id")
        _pager = await AgentRobotInstructModel.paginate(
            model=_model,
            page_no=params.page_no,
            page_size=params.page_size
        )

        # 处理数据
        _lists = []
        for item in _pager.lists:
            annex = json.loads(item["annex"] or "[]")
            for index, d in enumerate(annex):
                annex[index]["file_path"] = await UrlUtil.to_absolute_url(d["file_path"])

            _lists.append(schema.RobotInstructListVo(
                id=item["id"],
                scene=item["scene"],
                keyword=item["keyword"],
                content=item["content"],
                annex=annex,
                create_time=item["create_time"],
                update_time=item["update_time"]
            ))

        _pager.lists = _lists
        return _pager

    @classmethod
    async def add(cls, post: schema.RobotInstructAddIn, user_id: int):
        """
        指令新增。

        Args:
            post (schema.RobotInstructAddIn): 指令添加参数。
            user_id (int): 用户ID。

        Author:
            zero
        """
        # 验证智能体
        robot = await AgentRobotModel.filter(code=str(post.bot), is_delete=0).first()
        if robot is None:
            raise AppException("智能体不存在!")
        if robot.is_disable:
            raise AppException("智能体被禁用!")

        # 验证权限
        if robot.user_id != user_id:
            await RobotTeamedService.has_permission(robot.code, user_id, AgentEnum.POWER_ADMIN)

        # 验证重复
        ins = await AgentRobotInstructModel.filter(scene=post.scene, robot_id=robot.id, keyword=post.keyword).first()
        if ins:
            raise AppException("当前关键词已存在!")

        # 验证附件
        if len(post.annex) > 12:
            raise AppException("上传附件不能超出12个")

        # 附件处理
        annex = []
        for item in post.annex:
            annex.append({
                "file_type": item.get("file_type", ""),
                "file_name": item.get("file_name", ""),
                "file_size": item.get("file_size", 0),
                "file_ext": item.get("file_ext") or "",
                "file_path":  UrlUtil.to_relative_url(item.get("file_path", ""))
            })

        # 添加指令
        await AgentRobotInstructModel.create(
            robot_id=robot.id,
            scene=post.scene,
            keyword=post.keyword,
            content=post.content,
            annex=json.dumps(annex, ensure_ascii=False),
            create_time=int(time.time()),
            update_time=int(time.time())
        )

    @classmethod
    async def edit(cls, post: schema.RobotInstructEditIn, user_id: int):
        """
        指令编辑。

        Args:
            post (schema.RobotInstructEditIn): 指令编辑参数。
            user_id (int): 用户ID。

        Author:
            zero
        """
        # 验证智能体
        robot = await AgentRobotModel.filter(code=post.bot.strip(), is_delete=0).first()
        if robot is None:
            raise AppException("智能体不存在!")
        if robot.is_disable:
            raise AppException("智能体被禁用!")

        # 验证权限
        if robot.user_id != user_id:
            await RobotTeamedService.has_permission(robot.code, user_id, AgentEnum.POWER_ADMIN)

        # 验证重复
        ins = await AgentRobotInstructModel.filter(
            scene=post.scene,
            id__not=post.id,
            robot_id=robot.id,
            keyword=post.keyword
        ).first()
        if ins:
            raise AppException("当前关键词已存在!")

        # 验证附件
        if len(post.annex) > 12:
            raise AppException("上传附件不能超出12个")

        # 附件处理
        annex = []
        for item in post.annex:
            annex.append({
                "file_type": item.get("file_type", ""),
                "file_name": item.get("file_name", ""),
                "file_size": item.get("file_size", 0),
                "file_ext": item.get("file_ext", ""),
                "file_path": UrlUtil.to_relative_url(item.get("file_path", ""))
            })

        # 更新指令
        await AgentRobotInstructModel.filter(id=post.id).update(
            scene=post.scene,
            keyword=post.keyword,
            content=post.content,
            annex=json.dumps(annex, ensure_ascii=False),
            update_time=int(time.time())
        )

    @classmethod
    async def delete(cls, post: schema.RobotInstructDeleteIn, user_id: int):
        """
        指令删除。

        Args:
            post (schema.RobotInstructEditIn): 指令删除参数。
            user_id (int): 用户ID。

        Author:
            zero
        """
        # 验证智能体
        robot = await AgentRobotModel.filter(code=post.bot, is_delete=0).first()
        if robot is None:
            raise AppException("智能体不存在!".strip())
        if robot.is_disable:
            raise AppException("智能体被禁用!")

        # 验证权限
        if robot.user_id != user_id:
            await RobotTeamedService.has_permission(robot.code, user_id, AgentEnum.POWER_ADMIN)

        # 验证数据
        ins = await AgentRobotInstructModel.filter(id=post.id).filter(robot_id=robot.id).first()
        if ins is None:
            raise AppException("指令已不存在!")

        # 删除指令
        await AgentRobotInstructModel.filter(id=post.id, robot_id=robot.id).delete()
